Next | Prev | Up | Top | Contents | Index

Handling 32-Bit and 64-Bit Execution Models

The pfxioctl() entry point can be passed a data structure from the user process address space; that is, the arg value can be a pointer to a structure or an array of data. In order to interpret such a structure, the driver has to know the execution model for which the user process was compiled.

The execution model is specified when code is compiled. The 32-bit model (compiler option -32 or -n32) uses 32-bit address values and a long int contains 32 bits. The 64-bit model (compiler option -64) uses 64-bit address values and a long int contains 64 bits. (The size of an unqualified int is 32 bits in both models.) The execution model is sometimes casually called the "ABI" (Authorized Binary Interface), but this is an improper use of that term--an ABI comprises calling conventions, public names, and structure definitions, as well as the execution model.

An IRIX kernel compiled to the 32-bit model contains 32-bit drivers and supports only 32-bit user processes. A kernel compiled to the 64-bit model contains 64-bit drivers, but it supports user processes compiled to either 32-bit or 64-bit models. Therefore, in a 64-bit kernel, a driver can be asked to interpret data produced by a 32-bit program.

This is true only of the pfxioctl() and pfxpoll() entry points. Other driver entry points move data to and from user space as streams or blocks of bytes--not as a structure with fields to be interpreted.

Since in other respects it is easy to make your driver portable between 64-bit and 32-bit systems, you should design your driver so that it can handle the case of operating in a 64-bit kernel, receiving ioctl() requests alternately from 32-bit and 64-bit programs.

The simplest way to do this is to define the arguments passed to the entry points in such a way that they have the same precision in either system. However, this is not always possible. To handle the general case, the driver must know to which model the user process was compiled.

You find this out by calling the userabi() kernel function (for which, unfortunately, there is no reference page available).

The prototype of userabi() (declared in sys/ddi.h) is

int userabi(__userabi_t *);

If there is no user process context, userabi() returns ESRCH. Otherwise it fills out a __userabi_t structure and returns 0. The structure of type __userabi_t (declared in sys/types.h) contains the fields listed below:

uabi_szintSize of a user int (4).
uabi_szlongSize of a user long (4 or 8).
uabi_szptrSize of a user address (4 or 8).
uabi_szlonglongSize of a user long long (8).

Store the value of uabi_szptr when opening a device. Then you can use it to choose between 32-bit and 64-bit declarations of a structure passed to pfxioctl() or an address passed to pfxpoll().



Next | Prev | Up | Top | Contents | Index